package map.core;

import org.geotools.api.filter.FilterFactory;
import org.geotools.api.style.*;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.styling.SLD;

import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import static org.geotools.api.style.ColorMap.TYPE_VALUES;

public class RasterLayerStyle {

   private final static StyleFactory sf = CommonFactoryFinder.getStyleFactory();
    static FilterFactory ff = CommonFactoryFinder.getFilterFactory();

    private double noDataValue;

    //小于该值不显示
    private double clipMinValue = Double.MIN_VALUE;

    //大于该值不显示
    private double clipMaxValue = Double.MAX_VALUE;


    private boolean hasClipRange = false;

    List<StyleCategory> stopList = new ArrayList<>();
    List<StyleCategory> specialCategoryList = new ArrayList<>();



    public RasterLayerStyle(double noDataValue) {
        this.noDataValue = noDataValue;
    }


    public void setClipRange(double minValue,double maxValue){
        hasClipRange = true;
        this.clipMinValue = minValue;
        this.clipMaxValue = maxValue;
    }


    public double getNoDataValue() {
        return noDataValue;
    }

    public void setNoDataValue(double noDataValue) {
        this.noDataValue = noDataValue;
    }

    public void addStop(double value,int color){
        this.stopList.add(new StyleCategory(value,color));
    }


    //TODO
    public void addSpecialCategory(double value, int color){
        specialCategoryList.add(new StyleCategory(value,color));
    }

    public int[] getNoDataRGBA() {
        return new int[]{0,0,0,0};
    }

    public int[][] getsSpecialValueRGBA() {
        return new int[0][];
    }


    public static class StyleCategory{
        private double value;
        private Color color;

        public StyleCategory(double value, Color color) {
            this.value = value;
            this.color = color;
        }

        public StyleCategory(double value, int color) {
            this.value = value;
            this.color = new Color(color);
        }

        public double getValue() {
            return value;
        }

        public Color getColor() {
            return color;
        }
    }

    public Style getBaseStyle(){
        this.stopList.sort(Comparator.comparingDouble(o -> o.value));

        double minValue = this.stopList.get(0).value;
        double maxValue = this.stopList.get(this.stopList.size()-1).value;


        double clipMinValue = this.clipMinValue;
        double clipMaxValue =this.clipMaxValue;

        if(hasClipRange){
            if(clipMinValue >= minValue){
                throw new RuntimeException("minClipValue 必须小于" + minValue);
            }
            if(clipMaxValue <= maxValue){
                throw new RuntimeException("maxClipValue 必须小于" + maxValue);
            }
        }


        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ColorMap colorMap = sf.createColorMap();


        if(this.hasClipRange){
             colorMap.addColorMapEntry(createColorMapEntry(clipMinValue-0.000001, 0.0, Color.WHITE, "minClip"));
            colorMap.addColorMapEntry(createColorMapEntry(clipMinValue, 1.0, this.stopList.get(0).color, "maxClip"));

        }

        int index = 0;
         for (StyleCategory styleCategory : stopList) {
             index ++;
             ColorMapEntry entry = createColorMapEntry(styleCategory.value, 1.0, styleCategory.color, "stop_" + index);
             colorMap.addColorMapEntry(entry);
        }

        if(this.hasClipRange){
             colorMap.addColorMapEntry(createColorMapEntry(clipMaxValue, 1.0, this.stopList.get(this.stopList.size()-1).color, "maxClip"));
             colorMap.addColorMapEntry(createColorMapEntry(clipMaxValue + 0.0000001, 0.0, Color.WHITE, "maxClip"));
        }


        sym.setColorMap(colorMap);
        return SLD.wrapSymbolizers(sym);
    }


    private static ColorMapEntry createColorMapEntry(double quantity, double opacity, Color color, String label) {

        ColorMapEntry entry = sf.createColorMapEntry();
        entry.setOpacity(ff.literal(opacity));
        entry.setQuantity(ff.literal(quantity));
        entry.setColor(ff.literal(color));
        entry.setLabel(label);
        return entry;
    }

    public Style getNoDataStyle(){
        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ColorMap colorMap = sf.createColorMap();
        colorMap.setType(TYPE_VALUES);
        colorMap.addColorMapEntry(createColorMapEntry(noDataValue, 1.0, Color.WHITE, "noData"));
        sym.setColorMap(colorMap);
        return SLD.wrapSymbolizers(sym);
    }

    public Style getSpecialValueStyle(){
        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ColorMap colorMap = sf.createColorMap();
        colorMap.setType(TYPE_VALUES);

        int index = 0;
        for (StyleCategory styleCategory : specialCategoryList) {
            index ++;
            colorMap.addColorMapEntry(createColorMapEntry(styleCategory.value, 1.0, new Color(index), "specialValue_" + index));
        }

        sym.setColorMap(colorMap);
        return SLD.wrapSymbolizers(sym);
    }

}
